package com.cygsunri.util;

import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAdjusters;
import java.util.*;

public class DateUtil {

    /**
     * jdk1.7的SimpleDateFormat在多线程情况下不安全，建议使用jdk1.8的DateTimeFormatter
     */
    public static final DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .appendPattern("[yyyy][-MM][-dd][' 'HH][:mm][:ss]")
            .parseDefaulting(ChronoField.YEAR_OF_ERA, 1970)
            .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
            .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
            .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
            .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
            .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
            .parseDefaulting(ChronoField.MILLI_OF_SECOND, 0)
            .toFormatter();

    public static final DateTimeFormatter ymd = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    public static final DateTimeFormatter ym = DateTimeFormatter.ofPattern("yyyy-MM");
    public static final DateTimeFormatter y = DateTimeFormatter.ofPattern("yyyy");
    public static final DateTimeFormatter hms = DateTimeFormatter.ofPattern("HH:mm:ss");
    public static final DateTimeFormatter hm = DateTimeFormatter.ofPattern("HH:mm");
    public static final DateTimeFormatter ymd1 = DateTimeFormatter.ofPattern("yyyy/MM/dd");


    /**
     * 通用日期转换
     *
     * @param date 各种格式
     */
    public static LocalDateTime parse(String date) {
        return LocalDateTime.parse(date, formatter);
    }

    /**
            * 一天的前一天
     *
             * @param date 各种格式
     */
    public static String beforeDay(String date) {
        LocalDate l = parse(date).toLocalDate().minusDays(1);
        return l.format(ymd);
    }

    /**
     *  某一天的前*天
     *
     * @param date 各种格式
     */
    public static String beforeDay(String date,int i) {
        LocalDate l = parse(date).toLocalDate().minusDays(i);
        return l.format(ymd);
    }

    /**
     * 一月的前一月
     *
     * @param month 各种格式 2020-01
     */
    public static String beforeMonth(String month) {
        LocalDate l = parse(month).toLocalDate().minusMonths(1);
        return l.format(ym);
    }

    /**
     * 一年的前一年
     *
     * @param year 各种格式
     */
    public static String beforeYear(String year) {
        LocalDate l = parse(year).toLocalDate().minusYears(1);
        return l.format(y);
    }

    /**
     * 一天的00:00:00
     *
     * @param date yyyy-MM-dd HH:mm:ss
     */
    public static String startOfDay(String date) {
        return parse(date).with(LocalTime.MIN).format(formatter);
    }

    /**
     * 一天的24:00:00
     *
     * @param date yyyy-MM-dd HH:mm:ss
     */
    public static String endOfDay(String date) {
        return parse(date).plusDays(1).with(LocalTime.MIN).format(formatter);
    }

    /**
     * 一天的23:59:59
     *
     * @param date 各种格式
     */
    public static String endOfDayII(String date) {
        return parse(date).with(LocalTime.MAX).format(formatter);
    }

    /**
     * 当前时间戳 毫秒
     */
    public static long nowMilliSeconds() {
        return LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    /**
     * 当前时间戳 秒
     */
    public static long nowSeconds() {
        return LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
    }

    /**
     * 今日最小时间 yyyy-MM-dd 00:00:00 时间戳 秒
     */
    public static long startOfTodaySeconds() {
        return LocalDateTime.now().with(LocalTime.MIN).atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
    }

    /**
     * 今天yyyy-MM-dd
     */
    public static String today() {
        return LocalDate.now().format(ymd);
    }

    /**
     * 今天yyyy/MM/dd
     */
    public static String today1() {
        return LocalDate.now().format(ymd1);
    }

    /**
     * 昨日yyyy-MM-dd
     */
    public static String yesterday() {
        return LocalDate.now().minusDays(1).format(ymd);
    }

    /**
     * 当前时间yyyy-MM-dd HH:mm:ss
     */
    public static String nowString() {
        return LocalDateTime.now().format(formatter);
    }

    /**
     * 今日最小时间字符串 yyyy-MM-dd 00:00:00
     */
    public static String startOfToday() {
        return LocalDateTime.now().with(LocalTime.MIN).format(formatter);
    }

    /**
     * 今日最大时间字符串 yyyy-MM-dd 23:59:59
     */
    public static String endOfToday() {
        return LocalDateTime.now().with(LocalTime.MAX).format(formatter);
    }

    /**
     * 昨日最大时间戳 23:59:59
     */
    public static long lastDay() {
        return LocalDateTime.now().minusDays(1).with(LocalTime.MAX).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    /**
     * 昨日最大时间字符串 yyyy-MM-dd 23:59:59
     */
    public static String endOfLastDay() {
        return LocalDateTime.now().minusDays(1).with(LocalTime.MAX).format(formatter);
    }

    /**
     * 昨日最小时间字符串 yyyy-MM-dd HH:mm:ss
     */
    public static String startOfLastDay() {
        return LocalDateTime.now().minusDays(1).with(LocalTime.MIN).format(formatter);
    }

    /**
     * 上月最大时间戳 23:59:59
     */
    public static long lastMonth() {
        return LocalDateTime.now().minusMonths(1).with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    /**
     * 一个月有多少天
     */
    public static Integer getDaysOfMonth(LocalDateTime localDateTime) {
        return localDateTime.with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
    }

    /**
     * 判断选择的日期本月的第几天
     */
    public static Integer getWeeksByChooseDay(){
        Date date=new Date();
        Calendar ca=Calendar.getInstance();
        ca.setTime(date);
        return ca.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 判断选择的日期本月的第几天
     */
    public static Integer getDaysOfMonth(){
        return LocalDateTime.now().with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
    }

    /**
     * 判断是否为当年
     *
     * @param date 各种格式
     */
    public static boolean isThisYear(String date) {
        LocalDateTime l = LocalDateTime.parse(date, formatter);
        return LocalDate.now().getYear() == l.getYear();
    }

    /**
     * 判断是否为当月
     *
     * @param date 各种格式
     */
    public static boolean isThisMonth(String date) {
        LocalDateTime l = parse(date);
        return LocalDate.now().getMonth() == l.getMonth();
    }

    /**
     * 判断是否为当天
     *
     * @param date 各种格式
     */
    public static boolean isToday(String date) {
        LocalDateTime l = parse(date);
        return LocalDate.now().getDayOfYear() == l.getDayOfYear();
    }

    /**
     * 判断是否在今天之前
     *
     * @param date 各种格式
     */
    public static boolean isBeforeToday(String date) {
        LocalDate l = parse(date).toLocalDate();
        return LocalDate.now().isAfter(l);
    }

    /**
     * 获得前一年
     */
    public static LocalDateTime lastYear(LocalDateTime localDateTime) {
        return localDateTime.minusYears(1);
    }

    /**
     * 获取一年中最末的时间戳 23:59:59
     */
    public static long maxTimeOfYear(LocalDateTime localDateTime) {
        localDateTime = localDateTime.with(TemporalAdjusters.lastDayOfYear()).with(LocalTime.MAX);
        return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    /**
     * 获取两个时间相差的分钟数
     *
     * @return 分钟
     */
    public static int getDurationMinutes(String from, String to) {
        LocalDateTime start = LocalDateTime.parse(from, formatter);
        LocalDateTime end = LocalDateTime.parse(to, formatter);
        Duration duration = Duration.between(start, end);
        return (int) duration.toMinutes();
    }

    /**
     * 获取两个时间相隔的每一小时
     *
     * @return yyyy-MM-dd HH:mm:ss
     */
    public static List<String> getHours(String from, String to) {
        List<String> result = new ArrayList<>();
        LocalDateTime start = LocalDateTime.parse(from, formatter);
        LocalDateTime end = LocalDateTime.parse(to, formatter);
        Duration duration = Duration.between(start, end);
        long hours = duration.toHours();//相差的小时数
        int i = 0;
        while (i <= hours) {
            LocalDateTime l = start.plusHours(i);
            result.add(l.format(formatter));
            i++;
        }
        return result;
    }

    /**
     * 获取两个时间相隔的每一天
     *
     * @return yyyy-MM-dd
     */
    public static List<String> getDays(String from, String to) {
        List<String> result = new ArrayList<>();
        LocalDate start = LocalDate.parse(from, formatter);
        LocalDate end = LocalDate.parse(to, formatter);
        int days = (int) (end.toEpochDay() - start.toEpochDay());
        int i = 0;
        while (i <= days) {
            LocalDate l = start.plusDays(i);
            result.add(l.format(formatter));
            i++;
        }
        return result;
    }

    /**
     * 获取两个时间相隔的每个月
     *
     * @return yyyy-MM
     */
    public static List<String> getMonths(String from, String to) {
        List<String> result = new ArrayList<>();
        LocalDate start = LocalDate.parse(from, formatter);
        LocalDate end = LocalDate.parse(to, formatter);

        int month1 = start.getMonthValue();
        int year1 = start.getYear();

        int month2 = end.getMonthValue();
        int year2 = end.getYear();

        int diff = (year2 - year1) * 12 + (month2 - month1);
        int i = 0;
        while (i <= diff) {
            LocalDate l = start.plusMonths(i);
            result.add(l.format(ym));
            i++;
        }
        return result;
    }

    /**
     * 获取每小时
     *
     * @return 00:00:00 ~ 24:00:00
     */
    public static List<String> getHours() {
        List<String> result = new ArrayList<>();
        LocalTime l = LocalTime.parse("00:00:00", hms);
        int i = 0;
        while (i <= 24) {
            result.add(i != 24 ? l.plusHours(i).format(hms) : "24:00:00"); //LocalTime没有24点
            i++;
        }
        return result;
    }

    /**
     * 获取一天的每小时
     *
     * @return yyyy-MM-dd 00:00:00 ~ yyyy-MM-dd 24:00:00
     */
    public static List<String> getHours(String date) {
        List<String> result = new ArrayList<>();
        LocalDateTime l = LocalDateTime.parse(date + " " + "00:00:00", formatter);
        int i = 0;
        while (i <= 24) {
            result.add(i != 24 ? l.plusHours(i).format(formatter) : date + " " + "24:00:00"); //LocalTime没有24点
            i++;
        }
        return result;
    }

    /**
     * 获取一天的每十分钟
     *
     * @return yyyy-MM-dd 00:00:00 ~ yyyy-MM-dd 24:00:00
     */
    public static List<String> getTenMinutes() {
        List<String> result = new ArrayList<>();
        LocalDateTime l = LocalDateTime.now().with(LocalTime.MIN);
        long i = 0;
        while (i < 1440) {
            result.add(l.plusMinutes(i).format(formatter)); //LocalTime没有24点
            i += 10;
        }
        return result;
    }

    /**
     * 获取一月的每一天
     *
     * @param month yyyy-MM
     * @return yyyy-MM-dd
     */
    public static List<String> getDays(String month) {
        List<String> result = new ArrayList<>();
        LocalDateTime l = LocalDateTime.parse(month, formatter);
        int days = getDaysOfMonth(l);
        int i = 0;
        while (i < days) {
            LocalDate localDate = l.withDayOfMonth(1).toLocalDate().plusDays(i);
            result.add(localDate.format(ymd));
            i++;
        }
        return result;
    }

    /**
     * 获取一年的每一月
     *
     * @param year yyyy
     * @return yyyy-MM
     */
    public static List<String> getMonths(String year) {
        List<String> result = new ArrayList<>();
        LocalDate start = LocalDate.parse(year, formatter).withMonth(1);

        int i = 0;
        while (i < 12) {
            LocalDate l = start.plusMonths(i);
            result.add(l.format(ym));
            i++;
        }
        return result;
    }

    /**
     * 获取距离今天有多少天
     */
    public static int getDaysFromToday(String date) {
        LocalDate start = LocalDate.parse(date, formatter);
        return (int) (LocalDate.now().toEpochDay() - start.toEpochDay());
    }

    /**
     * 获取距离当前三十天
     *
     * @param date  yyyy-MM-dd
     * @param today 是否含当天
     * @return <yyyy-MM-dd>
     */
    public static List<String> getDays(String date, boolean today) {
        List<String> result = new ArrayList<>();
        LocalDateTime l = LocalDateTime.parse(date, formatter);
        int i = today ? 0 : 1;
        int num = today ? 30 : 31;
        while (i < num) {
            LocalDate localDate = l.toLocalDate().minusDays(i);
            result.add(localDate.format(ymd));
            i++;
        }
        Collections.reverse(result);
        return result;
    }

    /**
     * 获取环比时间
     *
     * @param time yyyy-MM-dd HH:mm:ss / yyyy-MM-dd / yyyy-MM
     * @return 日获取昨日，月获取上月，年获取去年
     */
    public static String getPeriodTime(String time) {
        LocalDateTime l = LocalDateTime.parse(time, formatter);
        //没找到好办法，先用长度判断
        int length = time.length();
        String period;
        if (length == 19) {
            period = l.minusDays(1).format(formatter);
        } else if (length == 10) {
            period = l.minusMonths(1).format(ymd);
        } else if (length == 7) {
            period = l.minusYears(1).format(ym);
        } else {
            period = null;
        }
        return period;
    }

    /**
     * 获取同比时间
     *
     * @param time yyyy-MM-dd HH:mm:ss / yyyy-MM-dd / yyyy-MM
     * @return 日获取去年同日，月获取去年同月，年获取去年
     */
    public static String getYoyTime(String time) {
        LocalDateTime l = LocalDateTime.parse(time, formatter);
        //没找到好办法，先用长度判断
        int length = time.length();
        String period;
        if (length == 19) {
            period = l.minusYears(1).format(formatter);
        } else if (length == 10) {
            period = l.minusYears(1).format(ymd);
        } else if (length == 7) {
            period = l.minusYears(1).format(ym);
        } else {
            period = null;
        }
        return period;
    }

    /**
     * 当月第一天起始时间 即：当月第一天日期
     *
     * @return yyyy-MM-dd
     */
    public static String firstDayOfCurrentMonth() {
        return LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()).format(ymd);
    }

    /**
     * 当年第一个月
     *
     * @return yyyy-MM
     */
    public static String firstMonthOfCurrentYear() {
        return LocalDate.now().with(TemporalAdjusters.firstDayOfYear()).format(ym);
    }

    /**
     * 上个月第一天起始时间 即：上个月第一天日期
     *
     * @return yyyy-MM-dd
     */
    public static String firstDayOfLastMonth() {
        return LocalDate.now().minusMonths(1).with(TemporalAdjusters.firstDayOfMonth()).format(ymd);
    }

    /**
     * 上个月最后一天结束时间 即：上个月最后一天日期
     *
     * @return yyyy-MM-dd
     */
    public static String lastDayOfLastMonth() {
        return LocalDate.now().minusMonths(1).with(TemporalAdjusters.lastDayOfMonth()).format(ymd);
    }

    /**
     * 上一年第一个月
     *
     * @return yyyy-MM
     */
    public static String firstMonthOfLastYear() {
        return LocalDate.now().minusYears(1).with(TemporalAdjusters.firstDayOfYear()).format(ym);
    }

    /**
     * 上一年最后一个月
     *
     * @return yyyy-MM
     */
    public static String lastMonthOfLastYear() {
        return LocalDate.now().minusYears(1).with(TemporalAdjusters.lastDayOfYear()).format(ym);
    }

    /**
     * 一个月第一天日期
     *
     * @return yyyy-MM-dd
     */
    public static LocalDateTime firstDayOfMonth(String date) {
        return parse(date).with(TemporalAdjusters.firstDayOfMonth());
    }

    /**
     * 一个月最后一天日期
     *
     * @return yyyy-MM-dd
     */
    public static LocalDateTime lastDayOfMonth(String date) {
        return parse(date).with(TemporalAdjusters.lastDayOfMonth());
    }

    /**
     * 一年第一个月
     *
     * @return yyyy-MM
     */
    public static LocalDateTime firstMonthOfYear(String date) {
        return parse(date).with(TemporalAdjusters.firstDayOfYear());
    }

    /**
     * 一年最后一个月
     *
     * @return yyyy-MM
     */
    public static LocalDateTime lastMonthOfYear(String date) {
        return parse(date).with(TemporalAdjusters.lastDayOfYear());
    }

    /**
     * 当月第一天日期
     *
     * @return yyyy-MM-dd
     */
    public static LocalDate firstDayOfCurrentMonthII() {
        return LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
    }

    /**
     * 当月最后一天日期
     *
     * @return yyyy-MM-dd
     */
    public static LocalDate lastDayOfCurrentMonthII() {
        return LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
    }

    /**
     * 将时间戳转换为时间
     */
    public static String stampToDate(String s){
        String res;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long lt = new Long(s);
        Date date = new Date(lt);
        res = simpleDateFormat.format(date);
        return res;
    }
}
